//
//  CustomPopupMenu.swift
//  swiftProject
//
//  Created by ZhangSai on 2021/6/17.
//

import UIKit

enum PopupMenuDirection : Int {
    case PopupMenuDirection_Auto
    case PopupMenuDirection_Up
    case PopupMenuDirection_Down

}

class CustomPopupMenu: UIView {
    var containerView = UIView()//容器，用于自定义弹窗内视图
    var imgBG:UIImage!//背景图，设置了这个就不用画带箭头的框了。
    var arrowH:CGFloat = 5//箭头形高
    var arrowW:CGFloat = 5//箭头形宽
    var minWidth:CGFloat = 0//弹窗最小宽度
    var popupMargin:CGFloat = 5//窗口距屏幕边缘最小距离
    var rowHeight:CGFloat = 45//行高
    var leftEdgeMargin:CGFloat = 16//左边距窗口的距
    var rightEdgeMargin:CGFloat = 16//右边距窗口的距离
    var textMargin:CGFloat = 5//文字距图标的距离
    var lineMargin:CGFloat = 0//分割线左边距
    var arrowCornerRadius:CGFloat = 6//箭头的圆角
    var cornerRadius:CGFloat = 6
    var lineColor:UIColor = UIColor.init(hexString: "#D8D8D8")//分割线颜色、边框色，默认系统灰色
    var textColor:UIColor!
    var fillColor:UIColor!//带箭头框的填充色，默认白色
    var textFont:UIFont = UIFont.systemFont(ofSize: 13)
    var needBorder:Bool = false//是否要边框
    var anchorPoint:CGPoint!//设置背景图的情况使用，背景图的三角在背景图的位置比例，如左上角(0,0),右下角(1,1),下边中间(0.5,1)以此类推
    var labelAry:Array<UILabel> = Array()
    var imageAry:Array<UIImageView>!
    var menuItems:Array<LFPopupMenuItem>!

    var isUp:Bool = false
    var ivBG:UIImageView!

    
    typealias ActionBlock = (_ index:Int) -> Void
    var actionBlock : ActionBlock!
    typealias DismissCompleteBlock = () -> Void
    var dismissComplete : DismissCompleteBlock!
    
    var direction:PopupMenuDirection = PopupMenuDirection.PopupMenuDirection_Auto
    
    override init(frame: CGRect) {
        super.init(frame: frame)
        containerView.backgroundColor = UIColor.clear
        self.addSubview(containerView)
    }
    
    required init?(coder: NSCoder) {
        fatalError("init(coder:) has not been implemented")
    }
    
    func configWithItems(items:Array<LFPopupMenuItem>,action:@escaping ActionBlock) {
        menuItems = items
        actionBlock = action
        self.adjustMaxWidth()
        containerView.frame = CGRect.init(x: 0, y: arrowH, width: Constants.screenWidth, height: Constants.screenHeight - arrowH)
        if imgBG == nil {
            ivBG = UIImageView.init(frame: self.bounds)
            ivBG.image = imgBG
            self.insertSubview(ivBG, at: 0)
        }
        labelAry = Array()
        imageAry = Array()
        for (i,item) in menuItems.enumerated() {
            let imgH = item.image.size.height
            let imgW = item.image.size.width
            
            let lb:UILabel = UILabel.init(frame: CGRect.init(x: leftEdgeMargin/2, y: rowHeight * CGFloat(i), width: Constants.screenWidth - imgW - rightEdgeMargin/2 - textMargin, height: rowHeight))
            
            let lbX:CGFloat = Constants.screenWidth - imgW - rightEdgeMargin/2 - textMargin
            let iv = UIImageView.init(frame: CGRect.init(x: lbX, y: (rowHeight - imgH)/2 + rowHeight * CGFloat(i), width: imgW, height: imgH))
            iv.image = item.image
            imageAry.append(iv)
            self.containerView.addSubview(iv)
            
            lb.textColor = textColor
            lb.text = item.title
            lb.font = UIFont.systemFont(ofSize: 15)
            labelAry.append(lb)
            containerView.addSubview(lb)
            
            let bt = UIButton.init(frame: CGRect.init(x: 0, y: CGFloat(i)*rowHeight, width: Constants.screenWidth, height: rowHeight))
            bt.backgroundColor = UIColor.clear
            bt.tag = i
            bt.addTarget(self, action: #selector(selectItem), for: .touchUpInside)
            containerView.addSubview(bt)

            if i > 0 {
                let viewLine = UIView.init(frame: CGRect.init(x: lineMargin, y: CGFloat(i)*rowHeight, width: Constants.screenWidth - lineMargin, height: 1.0/UIScreen.main.scale))
                viewLine.backgroundColor = lineColor
                containerView.addSubview(viewLine)
            }
        }
    }
    
    @objc func selectItem(button:UIButton) {
        if actionBlock != nil {
            actionBlock(button.tag)
        }
        self.dismiss()
    }
    
    func showArrowInPoint(point:CGPoint) {
        if direction == PopupMenuDirection.PopupMenuDirection_Up {
            isUp = true
        } else if direction == PopupMenuDirection.PopupMenuDirection_Down {
            isUp = false
        } else {
            isUp = point.y < self.maskView1.frame.size.height/2
        }
        self.private_showArrowInPoint(point: point)
    }
    
    func showArrowToView(view:UIView) {
        let pointViewRect:CGRect = (view.superview?.convert(view.frame, to: Constants.window))!
        var toPoint:CGPoint = CGPoint.init(x: pointViewRect.maxX, y: 0)
        if direction == PopupMenuDirection.PopupMenuDirection_Up {
            isUp = true
        } else if direction == PopupMenuDirection.PopupMenuDirection_Down {
            isUp = false
        } else {
            isUp = pointViewRect.maxY < self.maskView1.frame.size.height/2
        }
        
        if isUp {
            toPoint.y = pointViewRect.maxY + 2
        } else {
            toPoint.y = pointViewRect.maxY - 2
        }
        self.private_showArrowInPoint(point: toPoint)
    }
    
    @objc func dismiss() {
        if dismissComplete != nil {
            self.dismissComplete()
        }
        maskView1.removeFromSuperview()
        self.removeFromSuperview()
    }
    
    //根据字数调整最大宽度
    func adjustMaxWidth()  {
        var textW:CGFloat = 0
        var imageW:CGFloat = 0
        for item in menuItems {
            let rect:CGRect = (item.title as NSString).boundingRect(with: CGSize.zero, options: [NSStringDrawingOptions.truncatesLastVisibleLine,NSStringDrawingOptions.usesLineFragmentOrigin,NSStringDrawingOptions.usesFontLeading], attributes: [NSAttributedString.Key.font:self.textFont], context: nil)
            textW = textW > rect.size.width ? textW : rect.size.width;
            imageW = imageW > item.image.size.width ? imageW : item.image.size.width;
        }
        let totalMargin:CGFloat = (textW > 0 && imageW > 0) ? (self.leftEdgeMargin + self.rightEdgeMargin + self.textMargin) : (self.leftEdgeMargin + self.rightEdgeMargin);
        var totalWidth:CGFloat = textW + imageW + totalMargin;
        totalWidth = totalWidth > self.minWidth ? totalWidth : self.minWidth;
        self.frame = CGRect.init(x: 0, y: 0, width: totalWidth, height: self.rowHeight * CGFloat(self.menuItems.count) + self.arrowH);
    }
    
    func private_showArrowInPoint(point:CGPoint)  {
        var point = point
        self.addToWindow()
        var popupX:CGFloat = 0
        var popupY:CGFloat = 0
        // 如果箭头指向的点过于偏左或者过于偏右则需要重新调整箭头 x 轴的坐标
        let minHorizontalEdge:CGFloat = self.popupMargin + self.cornerRadius + self.arrowW/2;
        if (point.x < minHorizontalEdge) {
            point.x = minHorizontalEdge;
        }
        
        if (point.x > self.maskView1.frame.size.width - minHorizontalEdge) {
            point.x = self.maskView1.frame.size.width - minHorizontalEdge;
        }
        
        popupX = point.x - self.frame.size.width/2;
        popupY = point.y;
        //窗口靠左
        if (point.x <= self.frame.size.width/2 + self.popupMargin) {
            popupX = self.popupMargin;
        }
        //窗口靠右
        if (self.maskView1.frame.size.width - point.x <= self.frame.size.width/2 + self.popupMargin) {
            popupX = self.maskView1.frame.size.width - self.popupMargin - self.frame.size.width;
        }
        //箭头向下
        if (!self.isUp) {
            popupY = point.y - self.frame.size.height;
            self.containerView.frame = CGRect.init(x: 0, y: 0, width: self.frame.size.width, height: self.frame.size.height - self.arrowH);
        }
        
        self.frame = CGRect.init(x: popupX, y: popupY, width: self.frame.size.width, height: self.frame.size.height)
        
        // 箭头相对本窗口的坐标
        let arrowPoint:CGPoint = CGPoint.init(x: point.x - self.frame.minX, y: self.isUp ? 0 : self.frame.size.height)
        
        let maskTop:CGFloat = self.isUp ? self.arrowH : 0; // 顶部Y值
        let maskBottom:CGFloat = self.isUp ? self.frame.size.height : self.frame.size.height - self.arrowH; // 底部Y值
        
        let maskPath:UIBezierPath = UIBezierPath.init()
        // 左上圆角
        maskPath.move(to: CGPoint.init(x: 0, y: self.cornerRadius + maskTop))
        maskPath.addArc(withCenter: CGPoint.init(x: self.cornerRadius, y: self.cornerRadius + maskTop), radius: self.cornerRadius, startAngle: CGFloat(M_PI), endAngle: CGFloat(1.5*M_PI), clockwise: true)
        // 箭头朝上
        if isUp {
            maskPath.addLine(to: CGPoint.init(x: arrowPoint.x - arrowW/2, y: arrowH))
            maskPath.addQuadCurve(to: CGPoint.init(x: arrowPoint.x - arrowCornerRadius, y: arrowCornerRadius), controlPoint: CGPoint.init(x: arrowPoint.x - arrowW/2 + arrowCornerRadius, y: arrowH))
            maskPath.addQuadCurve(to: CGPoint.init(x: arrowPoint.x - arrowCornerRadius, y: arrowCornerRadius), controlPoint: arrowPoint)
            maskPath.addQuadCurve(to: CGPoint.init(x: arrowPoint.x + arrowW/2, y: arrowH), controlPoint: CGPoint.init(x: arrowPoint.x + self.arrowW/2 - self.arrowCornerRadius, y: arrowH))
        }
        // 右上圆角
        maskPath.addLine(to: CGPoint.init(x: self.frame.size.width - self.cornerRadius, y: maskTop))
        maskPath.addArc(withCenter: CGPoint.init(x: self.frame.size.width - self.cornerRadius, y: maskTop + self.cornerRadius), radius: self.cornerRadius, startAngle: CGFloat(1.5*M_PI), endAngle: 0, clockwise: true)
        // 右下圆角
        maskPath.addLine(to: CGPoint.init(x: self.frame.size.width, y: maskBottom - self.cornerRadius))
        maskPath.addArc(withCenter: CGPoint.init(x: self.frame.size.width - self.cornerRadius, y: maskBottom - self.cornerRadius), radius: self.cornerRadius, startAngle: 0, endAngle: CGFloat(M_PI), clockwise: true)
        if !isUp {
            maskPath.addLine(to: CGPoint.init(x: arrowPoint.x + self.arrowW/2, y: self.frame.size.height - self.arrowH))
            maskPath.addQuadCurve(to: CGPoint.init(x: arrowPoint.x + self.arrowCornerRadius, y: self.frame.size.height - self.arrowCornerRadius), controlPoint: CGPoint.init(x: arrowPoint.x + self.arrowW/2 - self.arrowCornerRadius, y: self.frame.size.height - self.arrowH))
            maskPath.addQuadCurve(to: CGPoint.init(x: arrowPoint.x - self.arrowCornerRadius, y:  self.frame.size.height - self.arrowCornerRadius), controlPoint: arrowPoint)
            maskPath.addQuadCurve(to: CGPoint.init(x: arrowPoint.x - self.arrowW/2, y: self.frame.size.height - self.arrowH), controlPoint: CGPoint.init(x: arrowPoint.x - self.arrowW/2 + self.arrowCornerRadius, y: self.frame.size.height - self.arrowH))
        }
        // 左下圆角
        maskPath.addLine(to: CGPoint.init(x: self.cornerRadius, y: maskBottom))
        maskPath.addArc(withCenter: CGPoint.init(x: self.cornerRadius, y:  maskBottom - self.cornerRadius), radius: self.cornerRadius, startAngle: 0.5*CGFloat(M_PI), endAngle: CGFloat(M_PI), clockwise: true)
        maskPath.close()
        
        let shapeLayer:CAShapeLayer = CAShapeLayer.init()
        shapeLayer.frame = self.bounds
        shapeLayer.path = maskPath.cgPath
        shapeLayer.lineWidth = 1/UIScreen.main.scale
        shapeLayer.fillColor = self.fillColor.cgColor
        shapeLayer.strokeColor = self.needBorder ? self.lineColor.cgColor : UIColor.clear.cgColor
        self.layer.insertSublayer(shapeLayer, at: 0)
        //弹出动画
        self.maskView1.alpha = 0
        let oldFrame:CGRect = self.frame
        self.layer.anchorPoint = CGPoint.init(x: arrowPoint.x/self.frame.size.width, y: self.isUp ? 0 : 1)
        self.frame = oldFrame
        self.transform = CGAffineTransform.init(scaleX: 0.01, y: 0.01)
        UIView.animate(withDuration: 0.25) {
            self.transform = CGAffineTransform.identity
            self.maskView1.alpha = 1;
        }
    }
    
    func addToWindow() {
        self.maskView1.frame = (Constants.window?.bounds)!
        Constants.window?.addSubview(self.maskView1)
        
        let tapGestureRecognizer:UITapGestureRecognizer = UITapGestureRecognizer.init(target: self, action: #selector(dismiss))
        
        self.maskView1.addGestureRecognizer(tapGestureRecognizer)
        Constants.window?.addSubview(self)
    }
    
    lazy var maskView1: UIView = {
        let maskView = UIView()
        maskView.backgroundColor = UIColor.clear
        return maskView
    }()
}
